import {TreeSelect, Spin} from 'antd';
import debounce from 'lodash/debounce';
import React, {useEffect, useMemo, useRef, useState} from 'react';

import type {TreeSelectProps} from 'antd';
import {DataNode} from "antd/es/tree";

export interface DebounceTreeSelectProps<ValueType = any>
  extends Omit<TreeSelectProps<ValueType>, 'treeData' | 'children'> {
  fetchOptions: (search: string) => Promise<ValueType[]>;
  debounceTimeout?: number;
  defaultTreeData?: ValueType[];
}

function DebounceTreeSelect<
  ValueType extends {
    key?: string;
    title: React.ReactNode;
    value: string | number;
    children?: ValueType[];
    [key: string]: any;
  } = any,
>({
    fetchOptions,
    defaultTreeData = [],
    debounceTimeout = 800,
    ...props
  }: DebounceTreeSelectProps<ValueType>) {
  const [fetching, setFetching] = useState(false);
  const [treeData, setTreeData] = useState<ValueType[]>(defaultTreeData);
  const fetchRef = useRef(0);

  const debounceFetcher = useMemo(() => {
    const loadOptions = (value: string) => {

      fetchRef.current += 1;
      const fetchId = fetchRef.current;
      setTreeData([]);
      setFetching(true);

      fetchOptions(value).then((newOptions) => {
        if (fetchId !== fetchRef.current) {
          // 确保请求回调顺序正确
          return;
        }

        setTreeData(newOptions);
        setFetching(false);
      });
    };

    return debounce(loadOptions, debounceTimeout);
  }, [fetchOptions, debounceTimeout]);

  useEffect(() => {
    debounceFetcher();
  }, [debounceFetcher]);

  return (
    <TreeSelect
      fieldNames={{
        label: 'name',
        value: 'id',
        children: 'children',
      }}

      showSearch
      allowClear
      // onSearch={}
      notFoundContent={fetching ? <Spin size="small"/> : null}
      treeData={treeData}
      {...props}
      treeData={treeData}
    />
  );
}

export default DebounceTreeSelect;
